package OLDSTUFF;

import HierarchyPackage.*;
import ClassifiedDataSetPackage.ClassifiedDataSet;
import DataSetPackage.View;
import OrderedCoverPackage.SC;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;

/**
 * Class for hierarchies representing intersections of other hierarchies.
 * @author Martin Haulrich
 */
public class IntersectionHierarchy implements Hierarchy, HierarchyThreaded {

    /**
     * This class is almost OK as it is. We only need to implement a new getClassifications method.
     * This should be pretty simple - look at the method in the ProductHierarchy.
     */
    @Override
    public ClassifiedDataSet getClassifications(Collection<Integer> dids, View dv, HClass topClass,
            int maxDepth, int minCount, int cutFraction, boolean saveData) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Set<HClass> getIntersection(HClass c1, HClass c2) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public HClass getTop() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getName(HClass c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean superclassOf(HClass c1, HClass c2) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean isClassifiedBy(Integer did, View dv, HClass classification) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Map<HClass, Integer> saveEst(String filename, Set<HClass> classes) throws IOException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Map<Integer, HClass> loadEst(String filename, Set<Integer> classIDs) throws IOException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getType() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public HClass newClass(Integer did, View v) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public ClassifiedDataSet getClassifications(Collection<Integer> dids, View dv, HClass topClass,
            int maxDepth, int minCount, int cutFraction, boolean saveData, ExecutorService pool) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public ClassifiedDataSet getClassifications(Collection<Integer> dids, View dv, HClass topClass, int maxDepth, int minCount, int cutFraction, boolean saveData, SC parentClasses,  int startdim) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
//
//    /**
//     * Hierarchies that this hierarchy is an intersection of.
//     */
//    Hierarchy[] hierarchies;
//
//    /**
//     * The TOP-class is this hierarchy.
//     */
//    IntersectionHClass top;
//
//    /**
//     * Constructor.
//     * Construct a new intersection hierarchy from existing hierarchies.
//     * @param hierarchies Hierarchies that this hierarchy should be an intersection of.
//     * Exception thrown when there are problems accesing the hierarchy.
//     */
//    public IntersectionHierarchy(Hierarchy[] hierarchies)  {
//        this.hierarchies = hierarchies;
//        HClass[] topClasses = new HClass[hierarchies.length];
//        for (int i = 0; i < hierarchies.length; i++) {
//            topClasses[i] = hierarchies[i].getTop();
//        }
//        top = new IntersectionHClass(this, topClasses);
//    }
//
//    @Override
//    public HClass getTop() {
//        return top;
//    }
//
//    @Override
//    public Set<HClass> getIntersection(HClass[] classes)  {
//
//        Set<HClass> result = new HashSet<HClass>();
//
//        for (HClass c : classes) {
//            if (!(c instanceof IntersectionHClass)) {
//                System.err.println("At least one class is not a IntersectionHClass");
//                return result;
//            }
//        }
//
//        Set<HClass> removeSet = new HashSet<HClass>();
//        for (int i = 0; i < classes.length; i++) {
//            IntersectionHClass ci = (IntersectionHClass) classes[i];
//            for (int j = i + 1; j < classes.length; j++) {
//                IntersectionHClass cj = (IntersectionHClass) classes[j];
//                if (superclassOf(ci, cj)) {
//                    removeSet.add(ci);
//                } else {
//                    if (superclassOf(cj, ci)) {
//                        removeSet.add(cj);
//                    }
//                }
//            }
//        }
//        result = new HashSet<HClass>(Arrays.asList(classes));
//        result.removeAll(removeSet);
//
//        return result;
//    }
//
//    @Override
//    public String getName(HClass c)  {
//        IntersectionHClass ic = (IntersectionHClass) c;
//
//        HClass[] cc = ic.getID();
//
//        String name = "";
//        boolean first = true;
//        for (int i = 0; i < hierarchies.length; i++) {
//
//            if (first) {
//                name = hierarchies[i].getName(cc[i]);
//                first = false;
//            } else {
//                name = name + " \u2229 " + hierarchies[i].getName(cc[i]);
//            }
//        }
//        return name;
//    }
//
//    @Override
//    public boolean superclassOf(HClass c1, HClass c2)  {
//
//
//        if (!((c1 instanceof IntersectionHClass) && (c2 instanceof IntersectionHClass))) {
//            return false;
//        }
//
//        IntersectionHClass ic1 = (IntersectionHClass) c1;
//        IntersectionHClass ic2 = (IntersectionHClass) c2;
//
//        // are all classes from c1 superclasses or equal to the corresponding classes in c2
//        boolean allsuporeq = true;
//        // is at lest one class from c1 a superclass to the corresponding class in c2
//        boolean existssuper = false;
//        HClass[] classes1 = ic1.getID();
//        HClass[] classes2 = ic2.getID();
//        if (classes1.length != classes2.length) {
//            return false;
//        }
//        for (int i = 0; i < classes1.length; i++) {
//            allsuporeq = allsuporeq && (hierarchies[i].superclassOf(classes1[i], classes2[i]) || (classes1[i].equals(classes2[i])));
//            if (hierarchies[i].superclassOf(classes1[i], classes2[i])) {
//                existssuper = true;
//            }
//
//        }
//        return allsuporeq && existssuper;
//
//    }
//
//    @Override
//    public ClassifiedDataSetStorage getClassifications(DataIDs dids, View dv, HClass topClass, int maxDepth, int minCount, boolean saveData)  {
//        /**
//         * @TODO minCount currently not in use
//         */
//        /**
//         * @TODO saveData currently not in use
//         */
//        ClassifiedDataSetStorage result = new ClassifiedDataSetStorage();
//
//        if (topClass instanceof IntersectionHClass) {
//
//            IntersectionHClass tC = (IntersectionHClass) topClass;
//
//            Runnable r = new IntersectThread(dids, dv, tC, maxDepth, result, minCount);
//            Thread t = new Thread(r);
//            t.start();
//
//            try {
//                t.join();
//            } catch (InterruptedException ex) {
//                ex.printStackTrace();
//            }
//        }
//        return result;
//    }
//
//    @Override
//    public ClassifiedDataSetStorage getClassifications(DataIDs dids, View dv, HClass topClass, int maxDepth, int minCount, boolean saveData, ExecutorService pool)  {
//
//        /**
//         * @TODO saveData currently not in use
//         */
//
//        ClassifiedDataSetStorage result = new ClassifiedDataSetStorage();
//
//        if (topClass instanceof IntersectionHClass) {
//
//            IntersectionHClass tC = (IntersectionHClass) topClass;
//
//            int maxThreads = 4;
//            DataIDs[] dd = dids.Split(maxThreads);
//
//            Future[] ff = new Future[maxThreads];
//            Set<Integer> running = new HashSet<Integer>();
//
//            for (int i = 0; i < maxThreads; i++) {
//
//                ff[i] = pool.submit(new IntersectThread(dd[i], dv, tC, maxDepth, result, minCount));
//                running.add(i);
//            }
//
//            while (!running.isEmpty()) {
//                try {
//                    Thread.sleep(100);
//                } catch (InterruptedException ex) {
//                    ex.printStackTrace();
//                }
//                for (int i = 0; i < maxThreads; i++) {
//                    if (ff[i].isDone()) {
//                        running.remove(i);
//                    }
//                }
//            }
//        }
//        return result;
//    }
//
//    @Override
//    public boolean isClassifiedBy(Integer did, View dv, HClass classification) , DataSetException {
//
//
//        if (dv instanceof IntersectionView) {
//            if (classification instanceof IntersectionHClass) {
//
//                IntersectionView sdv = (IntersectionView) dv;
//                IntersectionHClass sclas = (IntersectionHClass) classification;
//
//                HClass[] classes = sclas.getID();
//                boolean isClassified = true;
//                for (int i = 0; i < classes.length; i++) {
//                    int[] view = {i};
//                    View currentdv = dv.getView(view);
//                    isClassified = isClassified && hierarchies[i].isClassifiedBy(did, currentdv, classes[i]);
//                }
//                return isClassified;
//
//            } else {
//                throw new HierarchyException("classification is not in this class");
//            }
//        } else {
//            throw new HierarchyException("Wrong view type. Should be a SimpleView");
//        }
//
//    }
//
//    public synchronized IntersectionHClass getHClass(HClass[] clas) {
//        return new IntersectionHClass(this, clas);
//    }
//
//    /**
//     * Thread class performing classification.
//     */
//    private class IntersectThread implements Runnable {
//
//        /**
//         * IDs for the data that this thread classifies.
//         */
//        DataIDs dids;
//
//        /**
//         * View on the dataset.
//         */
//        View dv;
//
//        /**
//         * Class to classify with respect to.
//         */
//        IntersectionHClass topClass;
//
//        /**
//         * Maximun depth of classifications.
//         */
//        int maxDepth;
//
//        /**
//         * Result of the classification.
//         * This object is passed as a reference so all threads are writing to the same ClassifiedDataSetStorage.
//         */
//        ClassifiedDataSetStorage result;
//
//        /**
//         * Array containing the classes to classify with respect to from the diffent hierarchies.
//         */
//        HClass[] topClasses;
//
//        int minCount;
//
//        boolean saveData;
//
//        /**
//         * Constructor.
//         *
//         * @param dids IDs for the data that this thread classifies.
//         * @param dv View on the dataset.
//         * @param topClass View on the dataset.
//         * @param maxDepth Maximun depth of classifications.
//         * @param result Result of the classification.
//         * This object is passed as a reference so all threads are writing to the same ClasClassifiedDataSetMem
//         */
//        public IntersectThread(DataIDs dids, View dv, IntersectionHClass topClass, int maxDepth, ClassifiedDataSetStorage result, int minCount) {
//            this.dids = dids;
//            this.dv = dv;
//            this.topClass = topClass;
//            this.maxDepth = maxDepth;
//            this.result = result;
//            this.minCount = minCount;
//            topClasses = topClass.getID();
//        }
//
//        /**
//         * This method does most of the classification work.
//         * It is called revursively, startin with the leftmost index of the vector that makes up a intersectionHClass.
//         * It runs through all possible classification at this index, for each it class itself to find the classifications at the next indexes.
//         * @param clas The classification-class the method is currently working on.
//         * @param index Which part of the classification should this method-call find.
//         * @param remainingDepth How much depth are left for this and any succeding parts of the current classification.
//         * @param dset Classified dataset for the data with respect to the involved hierarchies.
//         * @param result The result of the classification.
//         * @param depth Depth the method is currently classified at.
//         * This is needen when the classifiation is added to <code>result</code>.
//         */
//        private void recursiveAdd(HClass[] clas, int index, int remainingDepth, ClassifiedDataSetStorage[] dset, ClassifiedDataSetStorage result, int depth) {
//
//            // Last point in classification
//            if ((index + 1) == hierarchies.length) {
//                if (remainingDepth == 0) {
//                    clas[index] = topClasses[index];
//
//                    IntersectionHClass ic = getHClass(clas);
//                    //result.addClassification(ic, depth);
//
//                    // Find instances...
//                    Set<Integer> iSet = new HashSet<Integer>();
//                    boolean first = true;
//                    for (int i = 0; i < hierarchies.length; i++) {
//                        HClass thisClas = clas[i];
//                        if (first) {
//                            iSet = new HashSet<Integer>(dset[i].getInstances(thisClas));
//                            first = false;
//                        } else {
//                            iSet.retainAll(dset[i].getInstances(thisClas));
//                        }
//                    }
//                    //result.addInstances(ic, iSet);
//                    result.addClassificationWithData(ic, depth, iSet);
//
//                } else {
//                    // Iterate through classifications that has a depth of remaningDepth
//                    for (Iterator<HClass> it = dset[index].classificationsAtDepth(remainingDepth).iterator(); it.hasNext();) {
//
//                        HClass c = it.next();
//
//                        clas[index] = c;
//
//
//                        IntersectionHClass ic = getHClass(clas);
//                        //result.addClassification(ic, depth);
//
//                        // Find instances...
//                        Set<Integer> iSet = new HashSet<Integer>();
//                        boolean first = true;
//                        for (int i = 0; i < hierarchies.length; i++) {
//
//                            HClass thisClas = clas[i];
//                            if (first) {
//                                iSet = new HashSet<Integer>(dset[i].getInstances(thisClas));
//                                first = false;
//                            } else {
//
//                                iSet.retainAll(dset[i].getInstances(thisClas));
//                            }
//                        }
//                        //result.addInstances(ic, iSet);
//                        result.addClassificationWithData(ic, depth, iSet);
//                    }
//                }
//            } else {
//                HClass c;
//                c = topClasses[index];
//                clas[index] = c;
//                recursiveAdd(clas, index + 1, remainingDepth, dset, result, depth);
//
//                for (int i = 1; i <= remainingDepth; i++) {
//                    for (Iterator<HClass> it = dset[index].classificationsAtDepth(i).iterator(); it.hasNext();) {
//                        c = it.next();
//                        clas[index] = c;
//                        recursiveAdd(clas, index + 1, remainingDepth - i, dset, result, depth);
//                    }
//                }
//            }
//        }
//
//        /**
//         * Initiates the classification.
//         * The method that is run when the thread is started.
//         */
//        @Override
//        public void run() {
//
//            ClassifiedDataSet[] dsets = new ClassifiedDataSetStorage[hierarchies.length];
//            for (int i = 0; i < hierarchies.length; i++) {
//                int[] view = {i};
//                //DataView currentdv = new DataView(dv, view);
//                View currentdv = dv.getView(view);
//
//
//                /**
//                 * @TODO Look at exceptionhandling for
//                 */
//                try {
//                    dsets[i] = hierarchies[i].getClassifications(dids, currentdv, topClasses[i], maxDepth, minCount, saveData);
//                } catch (Exception ex) {
//                    ex.printStackTrace();
//                    return;
//                }
//            }
//
//            //result.addClassification(topClass, 0);
//            Set<Integer> iSet = new HashSet<Integer>(dsets[0].getInstances(topClasses[0]));
//            for (int i = 1; i < hierarchies.length; i++) {
//                iSet.retainAll(dsets[i].getInstances(topClasses[i]));
//            }
//            //result.addInstances(topClass, iSet);
//            result.addClassificationWithData(topClass, 0, iSet);
//            for (int rd = 1; rd <= maxDepth; rd++) {
//                recursiveAdd(new HClass[hierarchies.length], 0, rd, dsets, result, rd);
//            }
//        }
//    }
//
//    @Override
//    public Map<HClass, Integer> saveEst(String filename, Set<HClass> classes) throws IOException {
//        throw new UnsupportedOperationException("Not supported yet.");
//    }
//
//    @Override
//    public Map<Integer, HClass> loadEst(String filename, Set<Integer> classIDs) throws IOException {
//        throw new UnsupportedOperationException("Not supported yet.");
//    }
//
//    @Override
//    public HClass newClass(Integer did, View v) {
//        throw new UnsupportedOperationException("Not supported yet.");
//    }
//
//    @Override
//    public Set<HClass> getIntersection(HClass c1, HClass c2)  {
//        throw new UnsupportedOperationException("Not supported yet.");
//    }
//
//    @Override
//    public String getType() {
//        return "IntersectionHierarchy";
//    }
//}
